package com.funmi.lizip.security.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

public class JsonAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (!request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }

        /*
        1. 既支持JSON形式传递参数，也支持key/value形式传递参数
        2. 通过contentType来判断当前请求。
        3. JSON传参则解析JSON，否则super.attemptAuthentication调用父类处理逻辑
         */
        String contentType = request.getContentType();
        if(contentType.equals(MediaType.APPLICATION_JSON_VALUE) || contentType.equals(MediaType.APPLICATION_JSON_UTF8_VALUE)) {
            // 支持JSON方式的登录数据
            UsernamePasswordAuthenticationToken authRequest = null;

            ObjectMapper objectMapper = new ObjectMapper();
            try(InputStream is = request.getInputStream()) {
                // 不希望创建对象，可以用Map获取
                Map<String, String> map = objectMapper.readValue(is, Map.class);

                String username = map.get("username");
                username = username != null ? username : "";
                username = username.trim();

                String password = map.get("password");
                password = password != null ? password : "";

                authRequest = new UsernamePasswordAuthenticationToken(username, password);
            } catch (IOException e) {
                //e.printStackTrace();
                // 出错后创建一个空Token，作为匿名用户
                authRequest = new UsernamePasswordAuthenticationToken("","");
            }

            // 继续UsernamePasswordAuthenticationFilter的处理流程
            this.setDetails(request, authRequest);
            return this.getAuthenticationManager().authenticate(authRequest);
        } else {
            // 如果不是JSON方式的登录数据，则仍然使用原来的key=value方式获取参数
            return super.attemptAuthentication(request, response);
        }
    }
}
